#pragma once
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cassert>

namespace cr
{
#define DefaultCapacity 8

    template <class T, class ref, class ptr>
    class __iterator
    {
    public:
        // 重命名的目的就是以便reverse_iterator可以进行复用
        typedef ref rref;
        typedef ptr rptr;

    public:
        __iterator() {}
        __iterator(char *str)
            : _str(str)
        {
        }

        ref operator*()
        {
            return *_str;
        }
        ptr operator++() // 前置++
        {
            _str++;
            return _str;
        }
        ptr operator++(int) // 后置++
        {
            ptr tmp = _str;
            _str++;
            return tmp;
        }
        ptr operator--() // 前置--
        {
            _str--;
            return _str;
        }
        ptr operator--(int) // 后置--
        {
            char *tmp = _str;
            _str--;
            return tmp;
        }
        bool operator!=(__iterator tmp)
        {
            return _str != tmp._str;
        }

    private:
        ptr _str;
    };

    // 采用容器适配器模式，模版参数就是迭代器类型
    template <class iterator> //
    class __reverse_iterator
    {
        typedef typename iterator::rref ref;
        typedef typename iterator::rptr ptr;

    public:
        __reverse_iterator(iterator it)
            : _it(it) // 浅拷贝
        {
        }

        ref operator*()
        {
            return *_it;
        }
        ptr operator++() // 前置++
        {
            return --_it;
        }
        ptr operator++(int) // 后置++
        {
            return _it--;
        }
        bool operator!=(__reverse_iterator tmp)
        {
            return _it != tmp._it;
        }

    private:
        iterator _it;
    };

    class MyString
    {
    public:
        size_t npose = -1;

    public:
        typedef __iterator<char, char &, char *> iterator;
        typedef __iterator<char, const char &, const char *> const_iterator;
        typedef __reverse_iterator<iterator> reverse_iterator;
        typedef __reverse_iterator<const_iterator> const_reverse_iterator;

        iterator begin()
        {
            return _str;
        }
        iterator end()
        {
            return _str + _sz;
        }
        // 重载begin和end（参数this进行const修饰）
        const_iterator begin() const
        {
            return _str;
        }
        const_iterator end() const
        {
            return _str + _sz;
        }

        reverse_iterator rbegin()
        {
            return iterator(_str + _sz - 1);
        }
        reverse_iterator rend()
        {
            return iterator(_str - 1);
        }
        const_reverse_iterator rbegin() const
        {
            return const_iterator(_str + _sz - 1);
        }
        const_reverse_iterator rend() const
        {
            return const_iterator(_str - 1);
        }

    public:
        // MyString()
        // {}
        MyString(const char *str = "")
            : _sz(strlen(str)), _capacity(DefaultCapacity)
        {
            while (_sz >= _capacity)
            {
                _capacity *= 2;
            }
            _str = new char[_capacity];
            memmove(_str, str, sizeof(char) * (_sz + 1)); // 将末尾的\0也拷贝进行
        }
        ~MyString()
        {
            delete[] _str;
            _str = nullptr;
            _sz = _capacity = 0;
        }
        MyString(const MyString &str) // 拷贝构造
            : _sz(str.size()), _capacity(DefaultCapacity)
        {
            while (_sz >= _capacity)
            {
                _capacity *= 2;
            }
            _str = new char[_capacity];
            memmove(_str, str.c_str(), sizeof(char) * (_sz + 1));
        }
        MyString operator=(const MyString &str) // 赋值重载
        {
            _sz = str.size();
            _capacity = str.capacity();

            MyString tmp(str); // 调用拷贝构造
            std::swap(_str, tmp._str);
            // 原数据与tmp中的数据交换，tmp出了作用域自动释放资源
            return *this;
        }

        void push_back(const char &c)
        {
            if (_sz + 1 >= _capacity) // 需要扩容
            {
                reverse(_capacity + 1);
            }
            _str[_sz++] = c;
            _str[_sz] = 0;
        }

        void append(const char *str)
        {
            for (int i = 0; i < strlen(str); i++)
            {
                push_back(str[i]);
            }
        }

        MyString &operator+=(const char &c)
        {
            push_back(c);
            return *this;
        }
        MyString &operator+=(const char *str)
        {
            append(str);
            return *this;
        }

        size_t find(char c, size_t pos = 0) const
        {
            for (int i = pos; i < _sz; i++)
            {
                if (c == _str[i])
                    return i;
            }
            return npose;
        }
        size_t find(const char *s, size_t pos = 0) const
        {
            int len = strlen(s);
            for (int i = pos; i <= _sz - len; i++)
            {
                int l = i, r = 0;
                while (r < len && _str[l] == s[r])
                {
                    l++;
                    r++;
                }
                if (r >= len)
                    return i;
            }
            return npose;
        }
        size_t find(const MyString &s, size_t pos = 0) const
        {
            return find(s._str, pos);
        }

        char &operator[](const size_t &index) const
        {
            assert(index < _sz);
            return _str[index];
        }

        bool operator<(const MyString &s)
        {
            int i = 0;
            int sz = std::min(_sz, s.size());
            while (i < _sz)
            {
                if (_str[i] < s._str[i])
                    return true;
                else if (_str[i] > s._str[i])
                    return false;
                i++;
            }
            if (_sz >= s.size())
                return false;
            return true;
        }
        bool operator<=(const MyString &s)
        {
            return this->operator<(s) || this->operator==(s);
        }
        bool operator>(const MyString &s)
        {
            return !this->operator<=(s);
        }
        bool operator>=(const MyString &s)
        {
            return !this->operator<(s);
        }
        bool operator==(const MyString &s)
        {
            return !this->operator!=(s);
        }
        bool operator!=(const MyString &s)
        {
            if (_sz != s.size())
                return true;
            int i = 0;
            while (i < _sz)
            {
                if (_str[i] != s._str[i])
                    return true;
                i++;
            }
            return false;
        }

        void reverse(const size_t &n)
        {
            // 缩容成本高
            if (n <= _capacity)
                return;
            while (n > _capacity)
            {
                _capacity *= 2;
            }
            char *tmp = _str;
            _str = new char[_capacity];
            memmove(_str, tmp, _sz + 1);
            delete[] tmp;
        }

        void resize(const size_t &n)
        {
            _sz = n;
            while (_sz >= _capacity)
            {
                _capacity *= 2;
            }
            char *tmp = new char[_capacity];
            memmove(tmp, _str, n);
            tmp[n] = 0;
            std::swap(_str, tmp);
        }
        void resize(const size_t &n, const char &c)
        {
            reverse(n);
            for (int i = _sz; i < n; i++)
            {
                _str[i] = c;
            }
            _str[n] = 0;
            _sz = n;
        }

        void clear()
        {
            _str[0] = 0;
            _sz = 0;
        }

        bool empty() const
        {
            return _sz == 0;
        }

        size_t size() const
        {
            return _sz;
        }

        size_t capacity() const
        {
            return _capacity;
        }

        const char *c_str() const
        {
            return _str;
        }

    private:
        char *_str;
        size_t _sz;
        size_t _capacity;

    private:
        friend std::ostream &operator<<(std::ostream &out, MyString &str);
        friend std::ostream &operator<<(std::ostream &out, const MyString &str);
        friend std::istream &operator>>(std::istream &out, MyString &str);
    };

    std::ostream &operator<<(std::ostream &out, MyString &str)
    {
        out << str.c_str();
        // out<<str._str;
        return out;
    }
    std::ostream &operator<<(std::ostream &out, const MyString &str)
    {
        // out << str.c_str();
        out << str._str;
        return out;
    }

    std::istream &operator>>(std::istream &in, MyString &str)
    {
        char tmp[1024] = {0};
        in >> tmp;
        str = tmp;
        return in;
    }
}